package com.hwd.gmall.cart.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.util.concurrent.AtomicDouble;
import com.hwd.gmall.cart.mapper.CartInfoMapper;
import com.hwd.gmall.cart.service.CartInfoService;
import com.hwd.gmall.common.constant.CartConst;
import com.hwd.gmall.common.util.MyThreadLocal;
import com.hwd.gmall.model.cart.CartInfo;
import com.hwd.gmall.model.product.SkuInfo;
import com.hwd.gmall.product.feign.ProductFeignClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 购物车管理的接口实现类
 *
 * @author 黄伟东/Victor
 * @date 2022/5/5 23:11
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CartInfoServiceImpl implements CartInfoService {

    @Resource
    private ProductFeignClient productFeignClient;

    @Resource
    private CartInfoMapper cartInfoMapper;

    /**
     * 新增购物车
     *
     * @param skuId  商品id
     * @param skuNum 新增商品数量
     */
    @Override
    public void saveCartInfo(Long skuId, Integer skuNum) {

        // 参数检验
        if (skuId == null || skuNum == null) {
            throw new RuntimeException("参数错误！skuId或skuNum不能为空！新增购物车失败！");
        }

        // 远程调用service-product微服务查询商品信息
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
        if (skuInfo == null || skuInfo.getId() == null) {
            throw new RuntimeException("商品不存在！新增购物车失败！");
        }

        // 从本地线程对象中获取用户名
        String username = MyThreadLocal.get();

        // 判断当前商品是否已经存在当前用户的购物车中
        CartInfo cartInfo = cartInfoMapper.selectOne(
                new LambdaQueryWrapper<CartInfo>()
                        .eq(CartInfo::getUserId, username).eq(CartInfo::getSkuId, skuId));

        if (cartInfo == null || cartInfo.getId() == null) {
            // 第一次新增购物车的时候，数量不能为负数
            if (skuNum <= 0) {
                throw new RuntimeException("参数错误！首次新增购物车数量需大于零！新增购物车新增购物车失败！");
            }
            // 购物车对象初始化
            cartInfo = new CartInfo();
            // 当前用户的购物车中没有该商品，新增，填充购物车对象属性值
            cartInfo.setUserId(username);
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuNum(skuNum);
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setCartPrice(productFeignClient.getSkuPrice(skuId));

            // 执行新增购物车
            int insert = cartInfoMapper.insert(cartInfo);
            if (insert <= 0) {
                throw new RuntimeException("新增购物车失败！");
            }
        } else {
            // 当前用户的购物车中有该商品，合并数量
            skuNum = cartInfo.getSkuNum() + skuNum;
            if (skuNum > 0) {
                // 合并数量
                cartInfo.setSkuNum(skuNum);
                // 执行更新，修改购物车该商品数量
                int update = cartInfoMapper.updateById(cartInfo);
                if (update < 0) {
                    throw new RuntimeException("新增购物车失败！");
                }
            } else {
                // 删除商品
                cartInfoMapper.deleteById(cartInfo.getId());
            }
        }

    }

    /**
     * 查询当前用户的购物车列表
     *
     * @return java.util.List<com.hwd.gmall.model.cart.CartInfo>
     */
    @Override
    public List<CartInfo> listCartInfo() {

        // 从本地线程对象中获取用户名
        String username = MyThreadLocal.get();

        return cartInfoMapper.selectList(
                new LambdaQueryWrapper<CartInfo>()
                        .eq(CartInfo::getUserId, username));
    }

    /**
     * 更新用户购物车商品的选中状态
     *
     * @param id     购物车商品id
     * @param status 选中状态，1:选中 0:不选中
     */
    @Override
    public void updateCartInfoStatus(Long id, Short status) {

        // 从本地线程对象中获取用户名
        String username = MyThreadLocal.get();

        int update;

        // 判断id是否为空
        if (id == null) {
            // 为空，代表全部选中/全部不选中，修改全部商品的选中状态
            update = cartInfoMapper.updateCartInfoStatusByUsername(username, status);
        } else {
            // id有值，代表修改单挑商品的选中状态
            update = cartInfoMapper.updateCartInfoStatusById(id, username, status);
        }

        if (update <= 0) {
            throw new RuntimeException("修改商品选中状态失败！");
        }
    }

    /**
     * 根据id删除购物车列表的商品
     *
     * @param id 购物车列表的商品id
     */
    @Override
    public void deleteCartInfo(Long id) {

        if (id == null) {
            return;
        }

        // 从本地线程对象中获取用户名
        String username = MyThreadLocal.get();

        int delete = cartInfoMapper.delete(new LambdaQueryWrapper<CartInfo>()
                .eq(CartInfo::getUserId, username).eq(CartInfo::getId, id));

        if (delete < 0) {
            throw new RuntimeException("删除购物车商品失败！");
        }
    }

    /**
     * 合并购物车
     *
     * @param cartInfos 购物车商品列表
     */
    @Override
    public void mergeCartInfo(List<CartInfo> cartInfos) {
        // 参数校验
        if (!cartInfos.isEmpty()) {
            cartInfos.stream().forEach(cartInfo ->
                    this.saveCartInfo(cartInfo.getSkuId(), cartInfo.getSkuNum()));
        }
    }

    /**
     * 查询当前用户订单确认页的购物车数据
     *
     * @return java.util.Map<java.lang.String, java.lang.Object>
     */
    @Override
    public Map<String, Object> listConfirmedCartInfo() {

        // 获取当前用户名
        String username = MyThreadLocal.get();

        // 获取本次用户要购买的商品数据
        List<CartInfo> cartInfoList = cartInfoMapper.selectList(
                new LambdaQueryWrapper<CartInfo>()
                        .eq(CartInfo::getUserId, username)
                        .eq(CartInfo::getIsChecked, CartConst.IS_CHECKED));

        // 判断用户是否没有选择任何商品
        if (cartInfoList.isEmpty()) {
            return null;
        }
        // 有数据，统计总数量和总金额
        AtomicInteger totalNumber = new AtomicInteger(0);
        AtomicDouble totalMoney = new AtomicDouble(0);

        List<CartInfo> cartInfoListNew = cartInfoList.stream().peek(cartInfo -> {
            // 获取本笔购物车数据商品的数量
            Integer skuNum = cartInfo.getSkuNum();
            // 获取本笔购物车数据商品的实时价格
            BigDecimal skuPrice = productFeignClient.getSkuPrice(cartInfo.getSkuId());
            // 存储实时价格
            cartInfo.setSkuPrice(skuPrice);
            // 计算本笔购物车数据商品的金额，金额累加
            totalMoney.getAndAdd(skuPrice.multiply(new BigDecimal(skuNum)).doubleValue());
            // 数量累加
            totalNumber.getAndAdd(skuNum);
        }).collect(Collectors.toList());

        // 保存总数量，总金额 ，购物车列表
        Map<String, Object> result = new HashMap<>(4);
        result.put("totalNumber", totalNumber);
        result.put("totalMoney", totalMoney);
        result.put("cartInfoList", cartInfoListNew);

        return result;

    }

    /**
     * 新增购物车后，清空购物车
     *
     * @return java.lang.Boolean
     */
    @Override
    public Boolean removeCartInfoAfterAddCartInfo() {
        // 获取用户名
        String username = MyThreadLocal.get();
        int delete = cartInfoMapper.delete(
                new LambdaQueryWrapper<CartInfo>()
                        .eq(CartInfo::getUserId, username)
                        .eq(CartInfo::getIsChecked, CartConst.IS_CHECKED));
        return delete > 0;
    }
}
